package edu.ucla.belief.ui.util;

import edu.ucla.belief.ui.actionsandmodes.*;
import edu.ucla.belief.ui.toolbar.MainToolBar;

import java.awt.event.ActionEvent;
import java.util.*;
import java.io.*;
import java.util.regex.*;

/**
	@author Keith Cascio
	@since 060404
*/
public class FileSystemUtil extends Object
{
	private static FileSystemUtil INSTANCE;

	private FileSystemUtil(){}

	public static FileSystemUtil instance()
	{
		if( INSTANCE == null ) INSTANCE = new FileSystemUtil();
		return INSTANCE;
	}

	public Collection find( File under, int depth, Pattern nameexpression, Pattern lineexpression )
	{
		if( (under == null) || (!under.exists()) || (!under.isDirectory())  ) return Collections.EMPTY_SET;
		if( depth < (int)0 ) return Collections.EMPTY_SET;
		if( nameexpression == null ) return Collections.EMPTY_SET;

		Collection ret = new LinkedList();
		find( under, depth, nameexpression, lineexpression, ret );
		return ret;
	}

	private void find( File under, int depth, Pattern nameexpression, Pattern lineexpression, Collection ret )
	{
		//System.out.println( "find( "+under.getAbsolutePath()+" )" );

		if( depth-- < 0 ) return;

		File[] files = under.listFiles();
		for( int i=0; i<files.length; i++ )
		{
			if( (depth >= 0) && (files[i].isDirectory()) ) find( files[i], depth, nameexpression, lineexpression, ret );
			else if( matches( files[i], nameexpression, lineexpression ) ) ret.add( files[i] );
		}
	}

	public boolean matches( File candidate, Pattern nameexpression, Pattern lineexpression )
	{
		String path = candidate.getPath();
		String name = path.substring( path.lastIndexOf( File.separator )+1 );

		//System.out.println( "matches( \""+name+"\" )" );

		if( nameexpression.matcher( name ).matches() )
		{
			if( lineexpression == null ) return true;
			else{
				try{
					return matches( new BufferedReader( new FileReader( candidate ) ), lineexpression );
				}catch( Exception e ){
					return false;
				}
			}
		}
		else return false;
	}

	public boolean matches( BufferedReader reader, Pattern lineexpression ) throws IOException
	{
		String line = null;
		while( (line = reader.readLine()) != null ){
			if( lineexpression.matcher( line ).find() ) return true;
		}
		return false;
	}

	public File newest( Collection files )
	{
		File current = null;
		long timeNewest = (long)0;
		File fileNewest = null;

		for( Iterator it = files.iterator(); it.hasNext(); ){
			current = (File) it.next();
			if( current.lastModified() > timeNewest ){
				timeNewest = current.lastModified();
				fileNewest = current;
			}
		}

		return fileNewest;
	}

	public static SamiamAction getAPIAction()
	{
		if( (ACTION_API_JAVADOCS == null) && FLAG_NOT_SEARCHED_YET )
		{
			FLAG_NOT_SEARCHED_YET = false;
			FileSystemUtil fsu = instance();
			final File newest = fsu.newest( fsu.find( new File("."), 1, Pattern.compile("index\\.html"), Pattern.compile("Generated by javadoc") ) );
			if( newest == null ) return (SamiamAction)null;
			else{
				ACTION_API_JAVADOCS = new SamiamAction( "API Javadocs", "View local Javadocs for the inference library API in your browser", 'a', MainToolBar.getIcon( "HelpAmber16.gif" ) )
				{
					public void actionPerformed( ActionEvent e ){
						BrowserControl.displayAbsolutePath( myPath );
					}

					private String myPath = newest.getAbsolutePath();
				};
			}
		}
		return ACTION_API_JAVADOCS;
	}

	private static SamiamAction ACTION_API_JAVADOCS = null;
	private static boolean FLAG_NOT_SEARCHED_YET = true;

	/** Test/debug */
	public static void main( String[] args )
	{
		FileSystemUtil fsu = FileSystemUtil.instance();

		File under = new File( "c:\\keithcascio\\release\\samiam23\\samiam23beta" );
		int depth = 1;
		Pattern nameexpression = Pattern.compile("index\\.html");
		Pattern lineexpression = Pattern.compile("Generated by javadoc");//(Pattern)null

		//System.out.println( "Searching under: " + under.getAbsolutePath() );
		Collection files = fsu.find( under, depth, nameexpression, lineexpression );
		Util.STREAM_TEST.println( "Found: " + files );
		Util.STREAM_TEST.println( "Newest: " + fsu.newest( files ) );
	}
}
